home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagd_f.zip / EGAVGA.SWG / 0139_ANIVGA Updates.pas < prev    next >
Pascal/Delphi Source File  |  1995-03-03  |  11KB  |  360 lines

  1. {
  2. > Would you please repost code of:
  3. > "the SpriteWidth, SpriteHeight, SpriteWidthExact, and flipping functions
  4. > you posted here quite a while ago" ?
  5.   Scanning  through  my database resulted in the following 2 snippets of
  6.   code  for  AniVGA V1.2 (again: it's only a quick-'n-dirty hack, use on
  7.   your  own  risk,  no  support,  no guarantees that the next version of
  8.   AniVGA will have these routines!):
  9. }
  10. {for the INTERFACE-section:}
  11.  FUNCTION SpriteHeight(Sp:WORD):WORD;
  12.  FUNCTION SpriteWidth(Sp:WORD):WORD;
  13.  FUNCTION SpriteWidthExact(Sp:WORD):WORD;
  14.  PROCEDURE ExchangeColor(Sp:WORD; oldColor,newColor:BYTE);
  15.  PROCEDURE MirrorSpriteVertical(Sp:WORD);
  16.  
  17. {for the IMPLEMENTATION-section:}
  18. FUNCTION SpriteHeight(Sp:WORD):WORD;
  19. { in: Sp = SpriteLADEnummer, dessen Hoehe ermittelt werden soll}
  20. {out: Die Hoehe des Sprites in Zeilen oder 0, wenn gar kein Sprite geladen}
  21. VAR ad:WORD;
  22. BEGIN
  23.  ad:=SPRITEAD[Sp];
  24.  IF (ad=0)
  25.   THEN SpriteHeight:=0  {Sprite noch nicht geladen}
  26.   ELSE SpriteHeight:=MEMW[ad:Hoehe]
  27. END;
  28.  
  29. FUNCTION SpriteWidth(Sp:WORD):WORD;
  30. { in: Sp = SpriteLADEnummer, dessen Breite ermittelt werden soll}
  31. {out: Die Breite des Sprites in Zeilen oder 0, wenn gar kein Sprite geladen}
  32. {rem: Der ermittelte Wert kann um bis zu 3 Punkte zu gross sein}
  33. VAR ad:WORD;
  34. BEGIN
  35.  ad:=SPRITEAD[Sp];
  36.  IF (ad=0)
  37.   THEN SpriteWidth:=0  {Sprite noch nicht geladen}
  38.   ELSE SpriteWidth:=MEMW[ad:Breite] SHL 2
  39. END;
  40.  
  41. FUNCTION SpriteWidthExact(Sp:WORD):WORD;
  42. { in: Sp = SpriteLADEnummer, dessen Breite ermittelt werden soll}
  43. {out: Die Breite des Sprites in Zeilen oder 0, wenn gar kein Sprite geladen}
  44. {rem: Der ermittelte Wert ist exakt, allerdings dauert die Routine etwas}
  45. {     laenger als SpriteWidth() }
  46. VAR ad,i,temp,planeOFS:WORD;
  47. BEGIN
  48.  ad:=SPRITEAD[Sp];
  49.  IF (ad=0)
  50.   THEN SpriteWidthExact:=0  {Sprite noch nicht geladen}
  51.   ELSE BEGIN
  52.         temp:=0; planeOFS:=MEMW[ad:Right];
  53.         FOR i:=0 TO MEMW[ad:Hoehe]-1 DO
  54.          BEGIN
  55.           IF MEMW[ad:planeOFS]>temp
  56.            THEN temp:=MEMW[ad:planeOFS];
  57.           INC(planeOFS,2)
  58.          END;
  59.         SpriteWidthExact:=temp+1
  60.        END;
  61. END;
  62.  
  63. PROCEDURE ExchangeColor(Sp:WORD; oldColor,newColor:BYTE);
  64. { in: Sp = SpriteLADEnummer des Sprites}
  65. {     oldColor = auszutauschende Farbe}
  66. {     newColor = neue Farbe}
  67. {out: Alle oldColor Farbwerte des Sprites Sp wurden gegen newColor ersetzt}
  68. {rem: Evtl. neue Grenzen, die sich daraus ergeben koennten, wenn eine der}
  69. {     Farben 0 ist, werden nicht neuberechnet}
  70. VAR ad,i,oneplanesize,planeOFS:WORD;
  71. BEGIN
  72.  ad:=SPRITEAD[Sp];
  73.  IF (ad<>0)
  74.   THEN BEGIN
  75.         oneplanesize:=MEMW[ad:Breite]*MEMW[ad:Hoehe]; {Groesse einer
  76. Spriteplane}        FOR i:=0 TO 3 DO
  77.          BEGIN
  78.           planeOFS:=MEMW[ad:i SHL 1];
  79.           ASM
  80.            MOV ES,ad
  81.            MOV DI,planeOFS
  82.            CLD
  83.            MOV AL,oldColor
  84.            MOV DL,newColor
  85.            MOV CX,oneplanesize
  86.           @goon:
  87.            REPNE SCASB
  88.            JNZ @nomatch
  89.            MOV ES:[DI-1],DL
  90.           @nomatch:
  91.            JCXZ @done
  92.            JMP @goon
  93.           @done:
  94.           END; {of ASM}
  95.          END; {of FOR}
  96.        END; {of IF}
  97. END;
  98.  
  99. PROCEDURE RevertWordArray(p:POINTER; len:WORD); ASSEMBLER;
  100. { in: p = Anfangsadresse eines Speicherbereichs,}
  101. {     len = Laenge dieses Bereichs in Worten}
  102. {out: Die Reihenfolge der Worte p[0*2]..p[(len-1)*2] wurde gespiegelt}
  103. ASM
  104.   MOV CX,len
  105.   MOV BX,CX
  106.   DEC BX
  107.   SHL BX,1
  108.   SHR CX,1
  109.   JCXZ @fertig
  110.   LDS SI,p
  111.   MOV DI,DS
  112.   MOV ES,DI
  113.   MOV DI,SI
  114.   ADD DI,BX
  115.   {DS:SI = 1.Word des Arrays, ES:DI = letztes Word des Arrays}
  116.   STD
  117.  @oneword:
  118.   MOV AX,ES:[DI]
  119.   XCHG AX,[SI]
  120.   STOSW
  121.   INC SI
  122.   INC SI
  123.   LOOP @oneword
  124.   CLD
  125.   MOV AX,SEG @Data
  126.   MOV DS,AX
  127.  @fertig:
  128. END;
  129.  
  130. PROCEDURE RevertByteGroups(p:POINTER; GroupsCount, GroupLen:WORD); ASSEMBLER;
  131. { in: p = Anfangsadresse eines Speicherbereichs,}
  132. {     GroupsCount = Anzahl Gruppen innerhalb dieses Bereichs,}
  133. {     GroupLen = Laenge einer einzelnen Gruppe in Bytes}
  134. {out: Die Reihenfolge der Gruppen wurde gespiegelt}
  135. {rem: Bsp.: 4 Gruppen a 3 Bytes: 01,02,03, 04,05,06, 07,08,09, 10,11,12}
  136. {           nach dem Aufruf    : 10,11,12, 07,08,09, 04,05,06, 01,02,03}
  137. ASM
  138.   MOV CX,GroupsCount
  139.   MOV AX,CX
  140.   SHR CX,1
  141.   JCXZ @fertig
  142.   DEC AX
  143.   MOV BX,GroupLen
  144.   MUL BX
  145.   LDS SI,p
  146.   MOV DI,DS
  147.   MOV ES,DI
  148.   MOV DI,SI
  149.   ADD DI,AX
  150.   {DS:SI = 1.Byte der 1.Gruppe, ES:DI = 1.Byte der letzten Gruppe,}
  151.   {BX = Breite einer Gruppe, CX = Anzahl Gruppen}
  152.   CLD
  153.  @outer:
  154.   MOV DX,BX
  155.  @inner:
  156.   MOV AL,ES:[DI]
  157.   XCHG AL,[SI]
  158.   STOSB
  159.   INC SI
  160.   DEC DX
  161.   JNZ @inner
  162.   SUB DI,BX
  163.   SUB DI,BX
  164.   LOOP @outer
  165.   MOV AX,SEG @Data
  166.   MOV DS,AX
  167.  @fertig:
  168. END;
  169.  
  170. PROCEDURE MirrorBoundaries(p:POINTER; len,m:WORD); ASSEMBLER;
  171. { in: p = Zeiger auf Anfang eines Wort-Bereiches,}
  172. {     len = Anzahl zu bearbeitende Worte,}
  173. {     m = Maximalwert, um den gespiegelt werden soll}
  174. {out: Die Werte des Bereichs wurden um (m-0)/2 gespiegelt;}
  175. {     Bsp.: [....a...b.] mit m=9 sollte gespiegelt (bei (9-0)/2 = 4.5) so aus-}
  176. {            0123456789
  177. {     sehen:[.b...a....]}
  178. {     Dadurch veraendern sich die Grenzen: Ist m der Maximalwert, so gilt fuer}
  179. {     die neuen Grenzen: neu:=(m-0)-alt}
  180. {rem: Die Sentinelwerte *16000 werden nicht veraendert!}
  181. ASM
  182.   MOV CX,len
  183.   JCXZ @fertig
  184.   CLD
  185.   MOV DX,m
  186.   LES DI,p
  187.   LDS SI,p
  188.  @oneword:
  189.   LODSW
  190.   CMP AX,+16000
  191.   JE @next
  192.   CMP AX,-16000
  193.   JE @next
  194.   NEG AX
  195.   ADD AX,DX
  196.   STOSW
  197.  @next:
  198.   LOOP @oneword
  199.   MOV AX,SEG @Data
  200.   MOV DS,AX
  201.  @fertig:
  202. END;
  203.  
  204. PROCEDURE MirrorSpriteVertical(Sp:WORD);
  205. { in: Sp = SpriteLADEnummer, das vertikal gespiegelt werden soll}
  206. {out: Das Sprites Sp wurde vertikal gespiegelt}
  207. VAR ad,i,zeilen,spalten:WORD;
  208. BEGIN
  209.  ad:=SPRITEAD[Sp];
  210.  IF (ad<>0)
  211.   THEN BEGIN
  212.         zeilen :=MEMW[ad:Hoehe];
  213.         spalten:=MEMW[ad:Breite];
  214.         {Zeilendaten per "Butterfly" vertauschen, fuer alle 4 Ebenen:}
  215.         FOR i:=0 TO 3 DO
  216.          RevertByteGroups(PTR(ad,MEMW[ad:i SHL 1]),zeilen,spalten);
  217.  
  218.         {Grenzdaten des oberen und unteren Spriterandes korrigieren:}
  219.         MirrorBoundaries(PTR(ad,MEMW[ad:Top]),spalten SHL 2,zeilen-1);
  220.         MirrorBoundaries(PTR(ad,MEMW[ad:Bottom]),spalten SHL 2,zeilen-1);
  221.  
  222.         {nun obere gegen untere Grenzdaten austauschen:}
  223.         i:=MEMW[ad:Top]; MEMW[ad:Top]:=MEMW[ad:Bottom]; MEMW[ad:Bottom]:=i;
  224.  
  225.         {Grenzdaten des linken und rechten Spriterandes mittauschen:}
  226.         RevertWordArray(PTR(ad,MEMW[ad:Left]),zeilen);
  227.         RevertWordArray(PTR(ad,MEMW[ad:Right]),zeilen);
  228.        END;
  229. END;
  230.  
  231.  
  232. {___snippet two___}
  233.  
  234. {The difference between the two routines is solely *where* the mirroring
  235. takes place: as default, the axis will be placed exactly in the midst of
  236. the sprite. However, as sprites are stored in multiples of 4 pixels in
  237. the X-direction, this "slack" of up to 3 pixels may be used to shift the
  238. mirror axes a bit to the right. --Don't think much about it: just use a
  239. sprite with a width of 5 pixels. (This will be rounded up to 2*4=8 pixels
  240. by MAKES automatically). Then run a small demo program and use Xshift
  241. values 0..3 to see what happens}
  242.  
  243.  
  244. {for the INTERFACE-section:}
  245.  
  246.  PROCEDURE MirrorSpriteHorizontalWithXShift(Sp,Xshift:WORD);
  247.  PROCEDURE MirrorSpriteHorizontal(Sp:WORD);
  248.  
  249. {for the IMPLEMENTATION-section:}
  250.  
  251. PROCEDURE RevertByteArray(p:POINTER; len:WORD); ASSEMBLER;
  252. { in: p = Anfangsadresse eines Speicherbereichs,}
  253. {     len = Laenge dieses Bereichs in Bytes}
  254. {out: Die Reihenfolge der Bytes p[0]..p[len-1] wurde gespiegelt}
  255. ASM
  256.   MOV CX,len
  257.   MOV BX,CX
  258.   DEC BX
  259.   SHR CX,1
  260.   JCXZ @fertig
  261.   LDS SI,p
  262.   MOV DI,DS
  263.   MOV ES,DI
  264.   MOV DI,SI
  265.   ADD DI,BX
  266.   {DS:SI = 1.Byte des Arrays, ES:DI = letztes Byte des Arrays}
  267.   STD
  268.  @onebyte:
  269.   MOV AL,ES:[DI]
  270.   XCHG AL,[SI]
  271.   STOSB
  272.   INC SI
  273.   LOOP @onebyte
  274.   CLD
  275.   MOV AX,SEG @Data
  276.   MOV DS,AX
  277.  @fertig:
  278. END;
  279.  
  280. PROCEDURE MirrorSpriteHorizontalWithXShift(Sp,Xshift:WORD);
  281. { in: Sp = SpriteLADEnummer, das horizontal gespiegelt werden soll}
  282. {     Xshift = Offset, um die Spiegelachse zusaetzlich verschoben werden soll}
  283. {out: Das Sprite Sp wurde horizontal gespiegelt}
  284. {rem: Normalerweise wird das Sprite um seine _tatsaechliche_ Mitte gespiegelt}
  285. {     (=per SpriteSpriteWidthExact() ermittelt). Da das Sprite jedoch in X- }
  286. {     Richtung als Vielfaches von 4 gespeichert wird, kann das Zentrum der  }
  287. {     Spiegelung noch geringfuegig verschoben werden!}
  288. {     Bsp.: Sprite ist 5 Punkte breit -> abgespeichert in 2 4er-Gruppen ->  }
  289. {           Spiegelung kann so erfolgen, als ob es 5,6,7 oder 8 Punkte breit}
  290. {           waere; XShift kann somit die Werte 5-5=0 .. 8-5=3 annehmen!}
  291. TYPE ByteAt=ARRAY[0..65534] OF BYTE;
  292. VAR ad,i,j,index,zeilen,spalten,exBreite,plane0,plane1,plane2,plane3:WORD;
  293.     p:POINTER;
  294. BEGIN
  295.  ad:=SPRITEAD[Sp];
  296.  IF (ad<>0)
  297.   THEN BEGIN
  298.         zeilen :=MEMW[ad:Hoehe];
  299.         spalten:=MEMW[ad:Breite];
  300.         exBreite:=SpriteWidthExact(Sp)+Xshift;
  301.         {Xshift-Addition darf nicht dazu fuehren, dass Sprite "aus dem }
  302.         {Rahmen" faellt:}
  303.         IF exBreite>spalten SHL 2
  304.          THEN exBreite:=spalten SHL 2;
  305.         GetMem(p,spalten SHL 2);  {Speicher fuer 1 Zeile}
  306.         plane0:=MEMW[ad: 0 SHL 1];
  307.         plane1:=MEMW[ad: 1 SHL 1];
  308.         plane2:=MEMW[ad: 2 SHL 1];
  309.         plane3:=MEMW[ad: 3 SHL 1];
  310.         index:=0; {Invariante: index = i*spalten + j}
  311.  
  312.         FOR i:=0 TO zeilen-1 DO
  313.     BEGIN
  314.           {Zeile expandieren:}
  315.           FOR j:=0 TO spalten-1 DO
  316.       BEGIN
  317.             ByteAt(p^)[j SHL 2 +0]:=MEM[ad:plane0 +index];
  318.             ByteAt(p^)[j SHL 2 +1]:=MEM[ad:plane1 +index];
  319.             ByteAt(p^)[j SHL 2 +2]:=MEM[ad:plane2 +index];
  320.             ByteAt(p^)[j SHL 2 +3]:=MEM[ad:plane3 +index];
  321.             INC(index)
  322.            END;
  323.           {Zeile spiegeln:}
  324.           RevertByteArray(p,exBreite);
  325.           {Zeile zurueckspeichern:}
  326.           DEC(index,spalten);  {auf Anfang der Zeile positionieren}
  327.           FOR j:=0 TO spalten-1 DO
  328.       BEGIN
  329.             MEM[ad:plane0 +index]:=ByteAt(p^)[j SHL 2 +0];
  330.             MEM[ad:plane1 +index]:=ByteAt(p^)[j SHL 2 +1];
  331.             MEM[ad:plane2 +index]:=ByteAt(p^)[j SHL 2 +2];
  332.             MEM[ad:plane3 +index]:=ByteAt(p^)[j SHL 2 +3];
  333.             INC(index)
  334.            END;
  335.          END;
  336.  
  337.         FreeMem(p,spalten SHL 2);
  338.  
  339.         {Grenzdaten des linken und rechten Spriterandes korrigieren:}
  340.         MirrorBoundaries(PTR(ad,MEMW[ad:Left]),zeilen,exBreite-1);
  341.         MirrorBoundaries(PTR(ad,MEMW[ad:Right]),zeilen,exBreite-1);
  342.  
  343.         {nun linke gegen rechte Grenzdaten austauschen:}
  344.         i:=MEMW[ad:Left]; MEMW[ad:Left]:=MEMW[ad:Right]; MEMW[ad:Right]:=i;
  345.  
  346.         {Grenzdaten des oberen und unteren Spriterandes mittauschen:}
  347.         RevertWordArray(PTR(ad,MEMW[ad:Top]),exBreite);
  348.         RevertWordArray(PTR(ad,MEMW[ad:Bottom]),exBreite);
  349.        END;
  350. END;
  351.  
  352. PROCEDURE MirrorSpriteHorizontal(Sp:WORD);
  353. { in: Sp = SpriteLADEnummer, das horizontal gespiegelt werden soll}
  354. {out: Das Sprites Sp wurde horizontal gespiegelt}
  355. BEGIN
  356.  MirrorSpriteHorizontalWithXShift(Sp,0)
  357. END;
  358.  
  359.  
  360.